package com.skp.shaphan.ui.dialogs;

import java.awt.Window;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.sql.Connection;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Vector;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.util.Callback;

import com.skp.shaphan.ShaphanApp;
import com.skp.shaphan.connect.BasicConnect;
import com.skp.shaphan.model.ConnectionDetails;
import com.skp.shaphan.savedConnections.ConnectionType;
import com.skp.shaphan.savedConnections.SavedConnection;
import com.skp.shaphan.savedConnections.SavedConnections;
import com.skp.shaphan.ui.fxconnectioncontrols.ConnectionController;
import com.skp.shaphan.ui.util.ShaphanJFXPanel.WindowAttachment;

public class ConnectionDialogController implements
		Initializable, WindowAttachment {
	@FXML private ListView<SavedConnection> connections;
	@FXML private TextField connName;
	@FXML private VBox connectionEditArea;
	@FXML private ComboBox<ConnectionType> dbTypeCombo;
	private Window window;
	private StringProperty connectionName = new SimpleStringProperty();
	private ConnectionController connectionController;

	@Override
	public void initialize(URL arg0, ResourceBundle arg1) {
		SavedConnections sc = SavedConnections.getInstance();
		ObservableList<SavedConnection> conns = FXCollections.observableArrayList();
		for(SavedConnection c : sc.getConnections()) {
			conns.add(c);
		}
		conns.add(new SavedConnection(true));
		connections.setItems(conns);
		connections.setCellFactory(new Callback<ListView<SavedConnection>, ListCell<SavedConnection>>() {
			@Override
			public ListCell<SavedConnection> call(ListView<SavedConnection> conn) {
				return new SavedConnectionCell();
			}
		});
		
		Vector<ConnectionType> types = sc.getConnectionTypes();
		ObservableList<ConnectionType> dbTypes = FXCollections.observableArrayList();
		for(ConnectionType type : types) {
			dbTypes.add(type);
		}
		dbTypeCombo.setItems(dbTypes);
		dbTypeCombo.setCellFactory(new Callback<ListView<ConnectionType>, ListCell<ConnectionType>>() {
			@Override
			public ListCell<ConnectionType> call(ListView<ConnectionType> conn) {
				return new ConnectionTypeCell();
			}
		});
		
		connName.textProperty().bind(connectionName);
	}
	
	static class SavedConnectionCell extends ListCell<SavedConnection> {

		@Override
		protected void updateItem(SavedConnection item, boolean empty) {
			super.updateItem(item, empty);
			if(item == null) {
				setText("Null!!");
			} else {
				setText(item.getName());
			}
		}
		
	}
	
	static class ConnectionTypeCell extends ListCell<ConnectionType> {

		@Override
		protected void updateItem(ConnectionType item, boolean empty) {
			super.updateItem(item, empty);
			if(item == null) {
				setText("Null!!");
			} else {
				setText(item.getName());
			}
		}
		
	}
	
	@FXML public void onConnectionsClicked(MouseEvent e) throws InstantiationException, IllegalAccessException {
		SavedConnection selectedConnection = connections.getSelectionModel().getSelectedItem();
		//connName.setText(selectedConnection.getName());
		connectionName.set(selectedConnection.getName());
		
		try {
			String className = selectedConnection.getTypeClass();
			className = className.replace("connectioncontrols", "fxconnectioncontrols");
			String fxmlPath = "/" + className.replace(".", "/") + ".fxml";
			URL location = getClass().getResource(fxmlPath);
			System.out.println("loading: " + fxmlPath);
			Class<?> controllerClass = Class.forName(className);
			connectionController = (ConnectionController) controllerClass.newInstance();
			connectionController.setProperties(selectedConnection.getProperties());
			FXMLLoader fxmlloader = new FXMLLoader(location);
			//fxmlloader.setRoot(this);
			fxmlloader.setController(connectionController);
			Parent control = (Parent)fxmlloader.load();
			connectionEditArea.getChildren().clear();
			connectionEditArea.getChildren().add(control);
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (ClassNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}
	
	@FXML public void onConnect(ActionEvent e) {
		SavedConnection selectedConnection = connections.getSelectionModel().getSelectedItem();
		try {
			@SuppressWarnings("unchecked")
			Class<BasicConnect> connectionClass = (Class<BasicConnect>) Class.forName("com.skp.shaphan.connect." + selectedConnection.getType());
			Constructor<BasicConnect> constructor = connectionClass.getConstructor(SavedConnection.class);
			BasicConnect connect = constructor.newInstance(selectedConnection);
			Properties props = connectionController.getProperties();
			Connection connection = connect.connect(props);
			if(connection != null) {
				ShaphanApp.getMainWindow().getSQLEditorsPane().setConnection(new ConnectionDetails(connection, ConnectionDetails.CONN_TYPE_ORACLE));
			}
		} catch (ClassNotFoundException e1) {
			e1.printStackTrace();
		} catch (NoSuchMethodException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (SecurityException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (InstantiationException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IllegalAccessException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IllegalArgumentException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (InvocationTargetException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}		
		window.dispose();
	}
	
	@FXML public void onCancel(ActionEvent e) {
		window.dispose();
	}

	public String getConnectionName() {
		return connectionName.get();
	}

	public void setConnectionName(String connectionName) {
		this.connectionName.set(connectionName);
	}

	@Override
	public void attachWindow(Window window) {
		this.window = window;
	}

	@FXML public void saveConnection(ActionEvent e) {
		SavedConnections sc = SavedConnections.getInstance();
		connectionController.getProperties().list(System.out);
		//sc.newConnection(connectionName, connectionOptions, properties)
		SavedConnection selectedConnection = connections.getSelectionModel().getSelectedItem();
		selectedConnection.getProperties().list(System.out);
		selectedConnection.updateProperties(connectionController.getProperties());
		selectedConnection.save();
	}
}
